home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / ObjectInputStream.java < prev    next >
Text File  |  1998-09-22  |  60KB  |  1,730 lines

  1. /*
  2.  * @(#)ObjectInputStream.java    1.41 98/07/09
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.io;
  16.  
  17. import java.util.Vector;
  18. import java.util.Stack;
  19. import java.util.Hashtable;
  20.  
  21. import sun.io.ObjectInputStreamDelegate; // RMI over IIOP hook.
  22.  
  23. /**
  24.  * An ObjectInputStream deserializes primitive data and objects previously
  25.  * written using an ObjectOutputStream.
  26.  * 
  27.  * ObjectOutputStream and ObjectInputStream can provide an application
  28.  * with persistent storage for graphs of objects when used with a
  29.  * FileOutputStream and FileInputStream respectively.
  30.  * ObjectInputStream is used to recover those objects previously
  31.  * serialized. Other uses include passing objects between hosts using
  32.  * a socket stream or for marshaling and unmarshaling arguments and
  33.  * parameters in a remote communication system.<p>
  34.  *
  35.  * ObjectInputStream ensures that the types of all objects in the
  36.  * graph created from the stream match the classes present in the
  37.  * Java Virtual Machine.  Classes are loaded as required using the
  38.  * standard mechanisms. <p>
  39.  *
  40.  * Only objects that support the java.io.Serializable or
  41.  * java.io.Externalizable interface can be read from streams.
  42.  *
  43.  * The method <STRONG>readObject</STRONG> is used to read an object
  44.  * from the stream.  Java's safe casting should be used to get the
  45.  * desired type.  In Java, strings and arrays are objects and are
  46.  * treated as objects during serialization. When read they need to be
  47.  * cast to the expected type.<p>
  48.  *
  49.  * Primitive data types can be read from the stream using the appropriate
  50.  * method on DataInput. <p>
  51.  * 
  52.  * The default deserialization mechanism for objects restores the
  53.  * contents of each field to the value and type it had when it was written.
  54.  * Fields declared as transient or static are ignored by the
  55.  * deserialization process.  References to other objects cause those
  56.  * objects to be read from the stream as necessary.  Graphs of objects
  57.  * are restored correctly using a reference sharing mechanism.  New
  58.  * objects are always allocated when deserializing, which prevents
  59.  * existing objects from being overwritten. <p>
  60.  *
  61.  * Reading an object is analogous to running the constructors of a new
  62.  * object.  Memory is allocated for the object and initialized to zero
  63.  * (NULL).  No-arg constructors are invoked for the non-serializable
  64.  * classes and then the fields of the serializable classes are
  65.  * restored from the stream starting with the serializable class closest to
  66.  * java.lang.object and finishing with the object's most specifiec
  67.  * class. <p>
  68.  *
  69.  * For example to read from a stream as written by the example in
  70.  * ObjectOutputStream: <br>
  71.  *
  72.  * <PRE>
  73.  *    FileInputStream istream = new FileInputStream("t.tmp");
  74.  *    ObjectInputStream p = new ObjectInputStream(istream);
  75.  *
  76.  *    int i = p.readInt();
  77.  *    String today = (String)p.readObject();
  78.  *    Date date = (Date)p.readObject();
  79.  *
  80.  *    istream.close();
  81.  * </PRE>
  82.  *
  83.  * Classes control how they are serialized by implementing either the
  84.  * java.io.Serializable or java.io.Externalizable interfaces.<P>
  85.  *
  86.  * Implementing the Serializable interface allows object serialization
  87.  * to save and restore the entire state of the object and it allows
  88.  * classes to evolve between the time the stream is written and the time it is
  89.  * read.  It automatically traverses references between objects,
  90.  * saving and restoring entire graphs.
  91.  *
  92.  * Serializable classes that require special handling during the
  93.  * serialization and deserialization process should implement both
  94.  * of these methods:<p>
  95.  *
  96.  * <PRE>
  97.  * private void writeObject(java.io.ObjectOutputStream stream)
  98.  *     throws IOException;
  99.  * private void readObject(java.io.ObjectInputStream stream)
  100.  *     throws IOException, ClassNotFoundException; 
  101.  * </PRE><p>
  102.  *
  103.  * The readObject method is responsible for reading and restoring the
  104.  * state of the object for its particular class using data written to
  105.  * the stream by the corresponding writeObject method.  The method
  106.  * does not need to concern itself with the state belonging to its
  107.  * superclasses or subclasses.  State is restored by reading data from
  108.  * the ObjectInputStream for the individual fields and making
  109.  * assignments to the appropriate fields of the object.  Reading
  110.  * primitive data types is supported by DataInput. <p>
  111.  *
  112.  * Serialization does not read or assign values to the fields of any
  113.  * object that does not implement the java.io.Serializable interface.
  114.  * Subclasses of Objects that are not serializable can be
  115.  * serializable. In this case the non-serializable class must have a
  116.  * no-arg constructor to allow its fields to be initialized.  In this
  117.  * case it is the responsibility of the subclass to save and restore
  118.  * the state of the non-serializable class. It is frequently the case that
  119.  * the fields of that class are accessible (public, package, or
  120.  * protected) or that there are get and set methods that can be used
  121.  * to restore the state. <p>
  122.  *
  123.  * Any exception that occurs while deserializing an object will be
  124.  * caught by the ObjectInputStream and abort the reading process. <p>
  125.  *
  126.  * Implementing the Externalizable interface allows the object to
  127.  * assume complete control over the contents and format of the object's
  128.  * serialized form.  The methods of the Externalizable interface,
  129.  * writeExternal and readExternal, are called to save and restore the
  130.  * objects state.  When implemented by a class they can write and read
  131.  * their own state using all of the methods of ObjectOutput and
  132.  * ObjectInput.  It is the responsibility of the objects to handle any
  133.  * versioning that occurs.
  134.  *
  135.  * @author  Roger Riggs
  136.  * @version 1.41, 07/09/98
  137.  * @see java.io.DataInput
  138.  * @see java.io.ObjectOutputStream
  139.  * @see java.io.Serializable
  140.  * @since   JDK1.1
  141.  */
  142. public class ObjectInputStream extends InputStream
  143.     implements ObjectInput, ObjectStreamConstants
  144.     /**
  145.      * Create an ObjectInputStream that reads from the specified InputStream.
  146.      * The stream header containing the magic number and version number
  147.      * are read from the stream and verified. This method will block
  148.      * until the corresponding ObjectOutputStream has written and flushed the header.
  149.      * @exception StreamCorruptedException The version or magic number are incorrect.
  150.      * @exception IOException An exception occurred in the underlying stream.
  151.      * @since     JDK1.1
  152.      */
  153.     public ObjectInputStream(InputStream in)
  154.     throws IOException, StreamCorruptedException
  155.   {
  156.         /*
  157.          * RMI over IIOP hook. Check if we are a trusted subclass
  158.          * that has implemented the "sun.io.ObjectInputStream"
  159.          * interface. If so, set our private flag that will be
  160.          * checked in "readObject", "defaultReadObject" and
  161.          * "enableResolveObject". Note that we don't initialize
  162.          * private instance variables in this case as an optimization
  163.          * (subclasses using the hook should have no need for them).
  164.          */
  165.         
  166.         if (this instanceof sun.io.ObjectInputStreamDelegate && this.getClass().getClassLoader() == null) {
  167.             isTrustedSubclass = true;
  168.             return;
  169.         }
  170.         
  171.       /*
  172.        * Save the input stream to read bytes from
  173.        * Create a DataInputStream used to read primitive types.
  174.        * Setup the DataInputStream to read from this ObjectInputStream
  175.        */
  176.     this.in = in;
  177.     dis  = new DataInputStream(this); 
  178.     readStreamHeader();
  179.     resetStream();
  180.     }
  181.  
  182.     /**
  183.      * Read an object from the ObjectInputStream.
  184.      * The class of the object, the signature of the class, and the values
  185.      * of the non-transient and non-static fields of the class and all
  186.      * of its supertypes are read.  Default deserializing for a class can be
  187.      * overriden using the writeObject and readObject methods.
  188.      * Objects referenced by this object are read transitively so
  189.      * that a complete equivalent graph of objects is reconstructed by readObject. <p>
  190.      *
  191.      * The root object is completly restored when all of its fields
  192.      * and the objects it references are completely restored.  At this
  193.      * point the object validation callbacks are executed in order
  194.      * based on their registered priorities. The callbacks are
  195.      * registered by objects (in the readObject special methods)
  196.      * as they are individually restored.
  197.      *
  198.      * Exceptions are thrown for problems with the InputStream and for classes
  199.      * that should not be deserialized.  All exceptions are fatal to the 
  200.      * InputStream and leave it in an indeterminate state; it is up to the caller
  201.      * to ignore or recover the stream state.
  202.      * @exception java.lang.ClassNotFoundException Class of a serialized object
  203.      *      cannot be found.
  204.      * @exception InvalidClassException Something is wrong with a class used by
  205.      *     serialization.
  206.      * @exception StreamCorruptedException Control information in the
  207.      *     stream is inconsistent.
  208.      * @exception OptionalDataException Primitive data was found in the 
  209.      * stream instead of objects.
  210.      * @exception IOException Any of the usual Input/Output related exceptions.
  211.      * @since     JDK1.1
  212.      */
  213.     public final Object readObject()
  214.      throws OptionalDataException, ClassNotFoundException, IOException {
  215.      
  216.          /*
  217.           * RMI over IIOP hook. Invoke delegate method if indicated.
  218.           */
  219.          if (isTrustedSubclass) {
  220.              return ((ObjectInputStreamDelegate) this).readObjectDelegate();
  221.          }
  222.          
  223.          /* require local Class for object by default. */
  224.          return readObject(true);
  225.     }
  226.  
  227.     /*
  228.       * Private implementation of Read an object from the ObjectInputStream.
  229.       *
  230.       * @param requireLocalClass If false, do not throw ClassNotFoundException
  231.       *                          when local class does not exist.
  232.       *
  233.       * @since     JDK1.2
  234.       */
  235.     private final Object readObject(boolean requireLocalClass)
  236.     throws OptionalDataException, ClassNotFoundException, IOException
  237.     {
  238.     /* If the stream is in blockData mode and there's any data
  239.      * left throw an exception to report how much there is.
  240.      */
  241.     if (blockDataMode) {
  242.         /* Can't use member method available() since it depends on the unreliable
  243.          *  method InputStream.available().
  244.          */
  245.         if (count == 0)
  246.         refill();
  247.         if (count > 0)
  248.         throw new OptionalDataException(count);
  249.     }
  250.     
  251.     /*
  252.      * Look ahead now to absorb any pending reset's.
  253.      * Before changing the state.
  254.      */
  255.     peekCode();
  256.  
  257.     /* Save the current state and get ready to read an object. */
  258.     Object prevObject = currentObject;
  259.     ObjectStreamClass prevClass = currentClassDesc;
  260.     boolean prevBlockDataMode = setBlockData(false);
  261.     
  262.     recursionDepth++;    // Entering
  263.     Object obj = null;
  264.  
  265.     /* 
  266.      * Check for reset, handle it before reading an object.
  267.      */
  268.  
  269.     byte rcode;
  270.     rcode = readCode();
  271.     try {
  272.         /*
  273.          * Dispatch on the next code in the stream.
  274.          */
  275.         int wireoffset = -1;
  276.  
  277.         switch (rcode) {
  278.         
  279.         case TC_NULL:
  280.         obj = null;
  281.         break;
  282.         
  283.         case TC_REFERENCE: 
  284.         /* This is a reference to a pre-existing object */
  285.         wireoffset = readInt() - baseWireHandle; 
  286.         
  287.         try {
  288.             obj = wireHandle2Object.elementAt(wireoffset);
  289.         } catch (ArrayIndexOutOfBoundsException e) {
  290.             throw new StreamCorruptedException("Reference to object never serialized.");
  291.         }
  292.         break;
  293.         
  294.         case TC_STRING:
  295.         {
  296.             obj = readUTF(); 
  297.             Object localObj = obj; //readUTF does not set currentObject
  298.             wireoffset = assignWireOffset(obj);
  299.  
  300.             /* Allow subclasses to replace the object */
  301.             if (enableResolve) {
  302.             obj = resolveObject(obj);
  303.             }
  304.  
  305.             if (obj != localObj)
  306.             wireHandle2Object.setElementAt(obj, wireoffset);
  307.         }
  308.         break;
  309.         
  310.         case TC_CLASS:
  311.         ObjectStreamClass v = 
  312.             (ObjectStreamClass)readObject(requireLocalClass);
  313.         if (v == null) {
  314.             /*
  315.              * No class descriptor in stream or class not serializable
  316.              */
  317.             throw new StreamCorruptedException("Class not in stream");
  318.         }
  319.         obj = v.forClass();
  320.         if (obj == null && requireLocalClass) {
  321.             throw new ClassNotFoundException(v.getName());
  322.         }
  323.         assignWireOffset(obj);
  324.         break;
  325.         
  326.         case TC_CLASSDESC:
  327.         obj = inputClassDescriptor();
  328.         break;
  329.         
  330.         case TC_ARRAY:
  331.         wireoffset = inputArray(requireLocalClass);
  332.         obj = currentObject;
  333.         /* Allow subclasses to replace the object */
  334.         if (enableResolve) {
  335.             obj = resolveObject(obj);
  336.         }
  337.  
  338.         if (obj != currentObject)
  339.             wireHandle2Object.setElementAt(obj, wireoffset);
  340.         break;
  341.         
  342.         case TC_OBJECT:
  343.         wireoffset = inputObject(requireLocalClass);
  344.         obj = currentObject;
  345.         if (enableResolve) {
  346.             /* Hook for alternate object */
  347.             obj = resolveObject(obj);
  348.             wireHandle2Object.setElementAt(obj, wireoffset);
  349.         }
  350.         break;
  351.         
  352.         case TC_ENDBLOCKDATA:
  353.         if (!prevBlockDataMode)
  354.             throw new StreamCorruptedException("Unexpected end of block data");
  355.         pushbackCode(TC_ENDBLOCKDATA);
  356.         count = -1;    /* Flag EOF */ 
  357.         throw new OptionalDataException(true);
  358.         
  359.         case TC_BLOCKDATA:
  360.         case TC_BLOCKDATALONG:
  361.         if (rcode == TC_BLOCKDATALONG) { /* long block: 32 bit size */
  362.             int b3 = in.read();
  363.             int b2 = in.read();
  364.             int b1 = in.read();
  365.             int b0 = in.read();
  366.             if ((b3 | b2 | b1 | b0) < 0)
  367.             throw new StreamCorruptedException("EOF expecting count");
  368.             count = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
  369.             if (count < 0)
  370.             throw new StreamCorruptedException("Negative block data size");
  371.         } else {            /* normal block: 8 bit size */
  372.             count = in.read();
  373.             if (count < 0)
  374.             throw new StreamCorruptedException("EOF expecting count");
  375.         }
  376.  
  377.             if (!prevBlockDataMode)
  378.             throw new StreamCorruptedException("Unexpected blockdata");
  379.         
  380.         throw new OptionalDataException(count);
  381.         
  382.         case TC_EXCEPTION:
  383.         /* An exception happened during writing, reset the
  384.          * stream, read the exception, reset the stream and
  385.          * throw a writeAbortedException with the exception
  386.          * that was read.
  387.          */
  388.         resetStream();
  389.         IOException ee = (IOException)readObject();
  390.         resetStream();
  391.         throw new WriteAbortedException("Writing aborted by exception", ee);
  392.  
  393.         default:
  394.         throw new StreamCorruptedException("Unknown code in readObject " + rcode);
  395.         }
  396.     } catch (OptionalDataException optdata) {
  397.         /* OptionalDataExceptions won't terminate everything.
  398.          * so just rethrow it.
  399.          */
  400.         throw optdata;
  401.     } catch(IOException ee) {
  402.         if (abortIOException == null && abortClassNotFoundException == null)
  403.         abortIOException = ee;
  404.     } catch(ClassNotFoundException ee) {
  405.         if (abortIOException == null && abortClassNotFoundException == null)
  406.         abortClassNotFoundException = ee;
  407.     } finally {
  408.         recursionDepth --;
  409.         currentObject = prevObject;
  410.         currentClassDesc = prevClass;
  411.         currentClass = currentClassDesc != null ? 
  412.         currentClassDesc.forClass() : null;
  413.         setBlockData(prevBlockDataMode);
  414.     }
  415.     
  416.     /* Check for thrown exceptions and re-throw them, clearing them if
  417.      * this is the last recursive call .
  418.      */
  419.     IOException exIOE = abortIOException;
  420.     if (recursionDepth == 0)
  421.         abortIOException = null;
  422.     if (exIOE != null)
  423.         throw exIOE;
  424.  
  425.     
  426.     ClassNotFoundException exCNF = abortClassNotFoundException;
  427.     if (recursionDepth == 0)
  428.         abortClassNotFoundException = null;
  429.     if (exCNF != null) {
  430.         throw exCNF;
  431.     }
  432.     
  433.     // Check if this is the last nested read, if so
  434.     // Call the validations
  435.     if (recursionDepth == 0) {
  436.         doValidations();
  437.     }
  438.  
  439.     return obj;
  440.     }
  441.  
  442.     /**
  443.      * Read the non-static and non-transient fields of the current class
  444.      * from this stream.  This may only be called from the readObject method
  445.      * of the class being deserialized. It will throw the NotActiveException
  446.      * if it is called otherwise.
  447.      *
  448.      * @exception java.lang.ClassNotFoundException if the class of a serialized
  449.      *              object could not be found.
  450.      * @exception IOException        if an I/O error occurs.
  451.      * @exception NotActiveException if the stream is not currently reading
  452.      *              objects.
  453.      * @since     JDK1.1
  454.      */
  455.     public final void defaultReadObject()
  456.     throws IOException, ClassNotFoundException, NotActiveException
  457.     {
  458.      
  459.     /*
  460.      * RMI over IIOP hook. Invoke delegate method if indicated.
  461.      */
  462.     if (isTrustedSubclass) {
  463.         ((ObjectInputStreamDelegate) this).defaultReadObjectDelegate();
  464.         return;
  465.     }
  466.          
  467.     if (currentObject == null || currentClassDesc == null)
  468.         throw new NotActiveException("defaultReadObject");
  469.     
  470.  
  471.     if (currentClassDesc.getFieldSequence() != null) {
  472.         boolean prevmode = setBlockData(false);
  473.         inputClassFields(currentObject, currentClass,
  474.                  currentClassDesc.getFieldSequence());
  475.         setBlockData(prevmode);
  476.     }
  477.     }
  478.     
  479.     /**
  480.      * Register an object to be validated before the graph is
  481.      * returned.  While similar to resolveObject these validations are
  482.      * called after the entire graph has been reconstituted.
  483.      * Typically, a readObject method will register the object with
  484.      * the stream so that when all of the objects are restored a final
  485.      * set of validations can be performed.
  486.      * @param obj the object to receive the validation callback.
  487.      * @param prio controls the order of callbacks;zero is a good default.
  488.      * Use higher numbers to be called back earlier, lower numbers for later
  489.      * callbacks. Within a priority, callbacks are processed in no
  490.      * particular order.
  491.      *
  492.      * @exception NotActiveException The stream is not currently reading objects
  493.      * so it is invalid to register a callback.
  494.      * @exception InvalidObjectException The validation object is null.
  495.      * @since     JDK1.1
  496.      */
  497.     public synchronized void registerValidation(ObjectInputValidation obj,
  498.                         int prio)
  499.     throws NotActiveException, InvalidObjectException
  500.     {
  501.     if (recursionDepth == 0) {
  502.         throw new NotActiveException("readObject not Active");
  503.     }
  504.     if (obj == null) {
  505.         throw new InvalidObjectException("Null is not a valid callback object");
  506.     }
  507.  
  508.     ValidationCallback cb = new ValidationCallback(obj, prio);
  509.  
  510.     if (callbacks == null) {
  511.         callbacks = new Vector(100,100);
  512.     }
  513.     // insert at the end if the priority is less than or equal to
  514.     // the last element.
  515.     if (callbacks.isEmpty() ||
  516.         ((ValidationCallback)(callbacks.lastElement())).priority >= prio) {
  517.         callbacks.addElement(cb);
  518.         return;
  519.     }
  520.  
  521.     // search for the element with priority that is <= to the new
  522.     // priority, insert before it. 
  523.     int size = callbacks.size();
  524.     for (int i = 0; i < size; i++) {
  525.         ValidationCallback curr = (ValidationCallback)callbacks.elementAt(i);
  526.         if (curr.priority <= prio) {
  527.         callbacks.insertElementAt(cb, i);
  528.         break;
  529.         }
  530.     }
  531.     }
  532.  
  533.     /*
  534.      * If any validations are pending, do them and cleanup the validation vector
  535.      * if an exception is raised, it is passed on to abort the deserialization.
  536.      */
  537.     private void doValidations() throws InvalidObjectException {
  538.     if (callbacks == null)
  539.         return;
  540.     
  541.     int size = callbacks.size();
  542.     if (size == 0)
  543.         return;
  544.     
  545.     for (int i = 0; i < size; i++) {
  546.         ValidationCallback curr = (ValidationCallback)callbacks.elementAt(i);
  547.         curr.callback.validateObject();
  548.     }
  549.     /* All pending validations completed successfully. Reset.*/
  550.     callbacks.setSize(0);
  551.     }
  552.  
  553.     /**
  554.      * Subclasses may implement this method to allow classes to be
  555.      * fetched from an alternate source. 
  556.      *
  557.      * The corresponding method in ObjectOutputStream is
  558.      * annotateClass.  This method will be invoked only once for each
  559.      * unique class in the stream.  This method can be implemented by
  560.      * subclasses to use an alternate loading mechanism but must
  561.      * return a Class object.  Once returned, the serialVersionUID of the
  562.      * class is compared to the serialVersionUID of the serialized class.
  563.      * If there is a mismatch, the deserialization fails and an exception
  564.      * is raised. <p>
  565.      *
  566.      * By default the class name is resolved relative to the class
  567.      * that called readObject. <p>
  568.      *
  569.      * @exception ClassNotFoundException If class of
  570.      * a serialized object cannot be found.
  571.      * @since     JDK1.1
  572.      */
  573.     protected Class resolveClass(ObjectStreamClass v)
  574.     throws IOException, ClassNotFoundException
  575.     {
  576.     /* Resolve by looking up the stack for a non-zero class
  577.      * loader. If not found use the system loader.
  578.      */
  579.     return loadClass0(null, v.getName());
  580.     }
  581.  
  582.     /* Resolve a class name relative to the specified class.  If the
  583.      * class is null find the first available class loader up the
  584.      * stack.  This will resolve classes relative to the caller of
  585.      * ObjectInputStream instead of the itself. Classes must be
  586.      * loaded/resolved relative to the application.
  587.      */
  588.     private native Class loadClass0(Class cl, String classname)
  589.     throws ClassNotFoundException;
  590.  
  591.     /**
  592.      * This method will allow trusted subclasses of ObjectInputStream
  593.      * to substitute one object for another during
  594.      * deserialization. Replacing objects is disabled until
  595.      * enableResolveObject is called. The enableResolveObject method
  596.      * checks that the stream requesting to resolve object can be
  597.      * trusted. Every reference to serializable objects is passed to
  598.      * resolveObject.  To insure that the private state of objects is
  599.      * not unintentionally exposed only trusted streams may use
  600.      * resolveObject. <p>
  601.      *
  602.      * This method is called after an object has been read but before it is
  603.      * returned from readObject.  The default resolveObject method
  604.      * just returns the new object. <p>
  605.      *
  606.      * When a subclass is replacing objects it must insure that the
  607.      * substituted object is compatible with every field where the
  608.      * reference will be stored.  Objects whose type is not a subclass
  609.      * of the type of the field or array element abort the
  610.      * serialization by raising an exception and the object is not be
  611.      * stored. <p>
  612.      *
  613.      * This method is called only once when each object is first encountered.
  614.      * All subsequent references to the object will be redirected to the
  615.      * new object. <P>
  616.      *
  617.      * @exception IOException Any of the usual Input/Output exceptions.
  618.      * @since     JDK1.1
  619.      */
  620.     protected Object resolveObject(Object obj)
  621.         throws IOException
  622.     {
  623.     return obj;
  624.     }
  625.  
  626.     /**
  627.      * Enable the stream to allow objects read from the stream to be replaced.
  628.      * If the stream is a trusted class it is allowed to enable replacment.
  629.      * Trusted classes are those classes with a classLoader equals null. <p>
  630.      * 
  631.      * When enabled the resolveObject method is called for every object
  632.      * being deserialized.
  633.      * 
  634.      * @exception SecurityException The classloader of this stream object is non-null.
  635.      * @since     JDK1.1
  636.      */
  637.     protected final boolean enableResolveObject(boolean enable)
  638.     throws SecurityException
  639.     {
  640.      
  641.     /*
  642.      * RMI over IIOP hook. Invoke delegate method if indicated.
  643.      */
  644.     if (isTrustedSubclass) {
  645.       return ((ObjectInputStreamDelegate) this).enableResolveObjectDelegate(enable);
  646.     }
  647.          
  648.     boolean previous = enableResolve;
  649.     if (enable) {
  650.         ClassLoader loader = this.getClass().getClassLoader();
  651.         if (loader == null) {
  652.         enableResolve = true;
  653.         return previous;
  654.         }
  655.         throw new SecurityException("Not trusted class");
  656.     } else {
  657.         enableResolve = false;
  658.     }
  659.     return previous;
  660.     }
  661.  
  662.  
  663.     /**
  664.      * The readStreamHeader method is provided to allow subclasses to
  665.      * read and verify their own stream headers. It reads and
  666.      * verifies the magic number and version number.
  667.      * @since     JDK1.1
  668.      */
  669.     protected void readStreamHeader()
  670.     throws IOException, StreamCorruptedException
  671.     {
  672.     short incoming_magic = readShort();
  673.     short incoming_version = readShort();
  674.     if (incoming_magic != STREAM_MAGIC)
  675.         throw new StreamCorruptedException("InputStream does not contain a serialized object");
  676.     
  677.     if (incoming_version != STREAM_VERSION)
  678.         throw new StreamCorruptedException("Version Mismatch, Expected " +
  679.                            STREAM_VERSION + " and got " +
  680.                            incoming_version);
  681.     }
  682.  
  683.     /*
  684.      * Read a ObjectStreamClasss from the stream, it may recursively
  685.      * create another ObjectStreamClass for the superclass it references.
  686.      */
  687.     private ObjectStreamClass inputClassDescriptor()
  688.     throws IOException, InvalidClassException, ClassNotFoundException
  689.     {
  690.  
  691.     /* Read the class name and hash */
  692.     Class aclass;
  693.     String classname = readUTF(); 
  694.     long hash = readLong();
  695.  
  696.     /* Read a new class version descriptor from the stream */
  697.     ObjectStreamClass v = new ObjectStreamClass(classname, hash);
  698.  
  699.     /* Assign the wire handle for this ObjectStreamClass and read it */
  700.     int wireoffset = assignWireOffset(v); 
  701.     v.read(this);
  702.  
  703.     /* Switch to BlockDataMode and call resolveClass.
  704.      * It may raise ClassNotFoundException.
  705.      * Consume any extra data or objects left by resolve class and
  706.      * read the endOfBlockData. Then switch out of BlockDataMode.
  707.      */
  708.     boolean prevMode = setBlockData(true);
  709.     try {
  710.         aclass = resolveClass((ObjectStreamClass)v);
  711.     } catch (ClassNotFoundException e) {
  712.         /* Not all classes in the serialized stream must be resolvable to
  713.          * a class in the current VM. The original version of a class need not
  714.          * resolve a superclass added by an evolved version of the class.
  715.             * ClassNotFoundException will be thrown if it is detected elsewhere
  716.          * that this class would be used as a most derived class.
  717.          */
  718.         aclass = null;
  719.      } catch (NoClassDefFoundError e) {
  720.          /* This exception was thrown when looking for an array of class,
  721.           * and class could not be found.
  722.           */
  723.          aclass = null;
  724.     }
  725.     SkipToEndOfBlockData();
  726.     prevMode = setBlockData(prevMode);
  727.  
  728.  
  729.     /* Verify that the class returned is "compatible" with
  730.      * the class description.  i.e. the name and hash match.
  731.      * Set the class this ObjectStreamClass will use to create 
  732.      * instances.
  733.      */
  734.     v.setClass(aclass);
  735.  
  736.     /* Get the superdescriptor of this one and it set it.
  737.      */
  738.     ObjectStreamClass superdesc = (ObjectStreamClass)readObject();
  739.     v.setSuperclass(superdesc);
  740.  
  741.     return v;
  742.     }
  743.  
  744.     /* Private routine to read in an array. Called from inputObject
  745.      * after the typecode has been read from the stream.
  746.      *
  747.      * @param requireLocalClass If false, do not throw ClassNotFoundException
  748.      *                          when local class does not exist.
  749.      */
  750.     private int inputArray(boolean requireLocalClass)
  751.     throws IOException, ClassNotFoundException
  752.     {
  753.     ObjectStreamClass v = (ObjectStreamClass)readObject();
  754.     Class arrayclass = v.forClass();
  755.     if (arrayclass == null && requireLocalClass)
  756.         throw new ClassNotFoundException(v.getName());
  757.  
  758.     /* This can't be done with new because only the top level array
  759.      * is needed and the type must be set properly.
  760.      * the lower level arrays will be created when they are read.
  761.      */
  762.     int length = readInt();
  763.     currentObject = (arrayclass == null) ? 
  764.         null : allocateNewArray(arrayclass, length);
  765.     int wireoffset = assignWireOffset(currentObject);
  766.     
  767.     /* Read in the values from the array,
  768.      * It dispatches using the type and read using the read* methods.
  769.      */
  770.     int i;
  771.  
  772.     if (arrayclass != null 
  773.         && arrayclass.getComponentType().isPrimitive()) {
  774.         Class type = arrayclass.getComponentType();
  775.         /* Arrays of primitive types read data in blocks and
  776.          * decode the data types from the buffer.
  777.          */
  778.         if (buffer == null)
  779.         buffer = new byte[1024];
  780.         int offset = buffer.length;
  781.         int buflen = buffer.length;
  782.  
  783.         if (type == Boolean.TYPE) {
  784.         boolean[] array = (boolean[])currentObject;
  785.         for (i = 0; i < length; i++) {
  786.             if (offset >= buflen) {
  787.             int readlen = Math.min(length-i, buflen);
  788.             readFully(buffer, 0, readlen);
  789.             offset = 0;
  790.             }
  791.             array[i] = (buffer[offset] != 0);
  792.             offset += 1;
  793.         }
  794.         } else if (type == Byte.TYPE) {
  795.         byte[] array = (byte[])currentObject;
  796.         int ai = 0;
  797.         while (ai < length) {
  798.             int readlen = Math.min(length-ai, buflen);
  799.             readFully(buffer, 0, readlen);
  800.             System.arraycopy(buffer, 0, array, ai, readlen);
  801.             ai += readlen;
  802.         }
  803.         } else if (type == Short.TYPE) {
  804.         short[] array = (short[])currentObject;
  805.         for (i = 0; i < length; i++) {
  806.             if (offset > buflen - 2) {
  807.             int readlen = Math.min((length-i)*2, buflen);
  808.             readFully(buffer, 0, readlen);
  809.             offset = 0;
  810.             }
  811.             array[i] = (short)(((buffer[offset] & 0xff) << 8) +
  812.                        ((buffer[offset+1] & 0xff) << 0));
  813.             offset += 2;
  814.         }
  815.         } else if (type == Integer.TYPE) {
  816.         int[] array = (int[])currentObject;
  817.         for (i = 0; i < length; i++) {
  818.             if (offset > buflen - 4) {
  819.             int readlen = Math.min((length-i)*4, buflen);
  820.             readFully(buffer, 0, readlen);
  821.             offset = 0;
  822.             }
  823.             array[i] = (((buffer[offset] & 0xff) << 24) +
  824.                 ((buffer[offset+1] & 0xff) << 16) +
  825.                 ((buffer[offset+2] & 0xff) << 8) +
  826.                 ((buffer[offset+3] & 0xff) << 0));
  827.             offset += 4;
  828.         }
  829.         } else if (type == Long.TYPE) {
  830.         long[] array = (long[])currentObject;
  831.         for (i = 0; i < length; i++) {
  832.             if (offset > buflen - 8) {
  833.             int readlen = Math.min((length-i)*8, buflen);
  834.             readFully(buffer, 0, readlen);
  835.             offset = 0;
  836.             }
  837.             int upper = (((buffer[offset] & 0xff) << 24) +
  838.                 ((buffer[offset+1] & 0xff) << 16) +
  839.                 ((buffer[offset+2] & 0xff) << 8) +
  840.                 ((buffer[offset+3] & 0xff) << 0));
  841.             int lower = (((buffer[offset+4] & 0xff) << 24) +
  842.                 ((buffer[offset+5] & 0xff) << 16) +
  843.                 ((buffer[offset+6] & 0xff) << 8) +
  844.                 ((buffer[offset+7] & 0xff) << 0));
  845.             array[i] = ((long)upper << 32) + ((long)lower & 0xFFFFFFFFL);
  846.             offset += 8;
  847.         }
  848.         } else if (type == Float.TYPE) {
  849.         float[] array = (float[])currentObject;
  850.         for (i = 0; i < length; i++) {
  851.             if (offset > buflen - 4) {
  852.             int readlen = Math.min((length-i)*4, buflen);
  853.             readFully(buffer, 0, readlen);
  854.             offset = 0;
  855.             }
  856.             int value = (((buffer[offset] & 0xff) << 24) +
  857.                  ((buffer[offset+1] & 0xff) << 16) +
  858.                  ((buffer[offset+2] & 0xff) << 8) +
  859.                  ((buffer[offset+3] & 0xff) << 0));
  860.             offset += 4;
  861.             array[i] = Float.intBitsToFloat(value);
  862.         }
  863.         } else if (type == Double.TYPE) {
  864.         double[] array = (double[])currentObject;
  865.         for (i = 0; i < length; i++) {
  866.             if (offset > buflen - 8) {
  867.             int readlen = Math.min((length-i)*8, buflen);
  868.             readFully(buffer, 0, readlen);
  869.             offset = 0;
  870.             }
  871.             int upper = (((buffer[offset] & 0xff) << 24) +
  872.                  ((buffer[offset+1] & 0xff) << 16) +
  873.                  ((buffer[offset+2] & 0xff) << 8) +
  874.                  ((buffer[offset+3] & 0xff) << 0));
  875.             int lower = (((buffer[offset+4] & 0xff) << 24) +
  876.                  ((buffer[offset+5] & 0xff) << 16) +
  877.                  ((buffer[offset+6] & 0xff) << 8) +
  878.                  ((buffer[offset+7] & 0xff) << 0));
  879.             offset += 8;
  880.             array[i] = Double.longBitsToDouble((((long)upper) << 32) +
  881.                                (lower & 0xFFFFFFFFL));
  882.         }
  883.         } else if (type == Character.TYPE) {
  884.         char[] array = (char[])currentObject;
  885.         for (i = 0; i < length; i++) {
  886.             if (offset > buflen - 2) {
  887.             int readlen = Math.min((length-i)*2, buflen);
  888.             readFully(buffer, 0, readlen);
  889.             offset = 0;
  890.             }
  891.             array[i] = (char)(((buffer[offset] & 0xff) << 8) +
  892.                       ((buffer[offset+1] & 0xff) << 0));
  893.             offset += 2;
  894.         }
  895.         } else {
  896.         throw new InvalidClassException(arrayclass.getName());
  897.         }
  898.     } else {        // Is array of objects
  899.         Object[] array = (Object[])currentObject;
  900.         boolean requiresLocalClass = (arrayclass != null);
  901.         for (i = 0; i < length; i++) {
  902.         Object obj = readObject(requiresLocalClass);
  903.         if (array != null)
  904.             array[i] = obj;
  905.         }
  906.     }
  907.  
  908.     return wireoffset;
  909.     }
  910.  
  911.     /*
  912.      * Read an instance of a class from the stream
  913.      * The new object typecode has already been read and used to dispatch to here.
  914.      * The ObjectStreamClass for the class is read and the class
  915.      * of the object retrieved from it.
  916.      * A new object is created of the specified class and
  917.      * each serializable class is processed using either
  918.      * the default serialization methods or class defined special methods
  919.      * if they have been defined.
  920.      * The handle for the object is returned, the object itself is in currentObject.
  921.      *
  922.      * @param requireLocalClass If false, do not throw ClassNotFoundException
  923.      *                          when local class does not exist.
  924.      */
  925.     private int inputObject(boolean requireLocalClass)
  926.     throws IOException, ClassNotFoundException
  927.     {
  928.     int handle = -1;
  929.     /*
  930.      * Get the descriptor and then class of the incomming object.
  931.      */
  932.     currentClassDesc = (ObjectStreamClass)readObject();
  933.     currentClass = currentClassDesc.forClass();
  934.  
  935.     /* require the class if required or if Externalizable data
  936.      * can not be skipped if it was not written in BlockData mode.
  937.      */
  938.     if (currentClass == null &&
  939.         (requireLocalClass ||
  940.          (currentClassDesc.isExternalizable() &&
  941.           !currentClassDesc.hasExternalizableBlockDataMode())))
  942.         throw new ClassNotFoundException(currentClassDesc.getName());
  943.     
  944.  
  945.     /* If Externalizable,
  946.      *  Create an instance and tell it to read its data.
  947.      * else,
  948.      *  Handle it as a serializable class.
  949.      */
  950.     if (currentClassDesc.isExternalizable()) {
  951.         try {
  952.         currentObject = (currentClass == null) ?
  953.             null : allocateNewObject(currentClass, currentClass);
  954.         handle = assignWireOffset(currentObject);
  955.         boolean prevmode = blockDataMode;
  956.         if (currentClassDesc.hasExternalizableBlockDataMode()) {
  957.             prevmode = setBlockData(true);
  958.         }
  959.         try {
  960.             if (currentObject != null) {
  961.             Externalizable ext = (Externalizable)currentObject;
  962.             ext.readExternal(this);
  963.             }
  964.         } finally {
  965.             if (currentClassDesc.hasExternalizableBlockDataMode()) {
  966.             SkipToEndOfBlockData();
  967.             setBlockData(prevmode);
  968.             }
  969.         }
  970.         } catch (IllegalAccessException e) {
  971.         throw new InvalidClassException(currentClass.getName(),
  972.                         "IllegalAccessException");
  973.         } catch (InstantiationException e) {
  974.         throw new InvalidClassException(currentClass.getName(),
  975.                         "InstantiationException");
  976.         }
  977.     } else {
  978.         /* Count number of classes and descriptors we might have
  979.          * to work on.
  980.          */
  981.         ObjectStreamClass currdesc = currentClassDesc;
  982.         Class currclass = currentClass;
  983.  
  984.         int spBase = spClass;    // current top of stack
  985.  
  986.         /* The object's classes should be processed from supertype to subtype
  987.          * Push all the clases of the current object onto a stack.
  988.          * Note that only the serializable classes are represented
  989.          * in the descriptor list. 
  990.          *
  991.          * Handle versioning where one or more supertypes of
  992.          * have been inserted or removed.  The stack will
  993.          * contain pairs of descriptors and the corresponding
  994.          * class.  If the object has a class that did not occur in
  995.          * the original the descriptor will be null.  If the
  996.          * original object had a descriptor for a class not
  997.          * present in the local hierarchy of the object the class will be
  998.          * null.
  999.          *
  1000.          */
  1001.  
  1002.         /*
  1003.          * This is your basic diff pattern, made simpler
  1004.          * because reordering is not allowed.
  1005.          */
  1006.         for (currdesc = currentClassDesc, currclass = currentClass;
  1007.          currdesc != null;
  1008.          currdesc = currdesc.getSuperclass()) {
  1009.  
  1010.         /*
  1011.          * Search the classes to see if thisthe class of this
  1012.          * descriptor appears further up the hierarchy. Until
  1013.          * it's found assume its an inserted class.  If it's
  1014.          * not found, its the descriptor's class that has been
  1015.          * removed.
  1016.          */
  1017.         Class cc = currdesc.forClass();
  1018.         Class cl;
  1019.         for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  1020.             if (cc == cl) {
  1021.             // found a superclass that matches this descriptor
  1022.             break;
  1023.             } else {
  1024.             /* Ignore a class that doesn't match.  No
  1025.              * action is needed since it is already
  1026.              * initialized.
  1027.              */
  1028.             }
  1029.         }
  1030.         /* Test if there is room for this new entry.
  1031.          * If not, double the size of the arrays and copy the contents.
  1032.          */
  1033.         spClass++;
  1034.         if (spClass >= classes.length) {
  1035.             int newlen = classes.length * 2;
  1036.             Class[] newclasses = new Class[newlen];
  1037.             ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  1038.  
  1039.             System.arraycopy(classes, 0,
  1040.                  newclasses, 0,
  1041.                  classes.length);
  1042.             System.arraycopy(classdesc, 0,
  1043.                      newclassdesc, 0,
  1044.                      classes.length);
  1045.  
  1046.             classes = newclasses;
  1047.             classdesc = newclassdesc;
  1048.         }
  1049.  
  1050.         if (cl == null) {
  1051.             /* Class not found corresponding to this descriptor.
  1052.              * Pop off all the extra classes pushed.
  1053.              * Push the descriptor and a null class.
  1054.              */
  1055.             classdesc[spClass] = currdesc;
  1056.             classes[spClass] = null;
  1057.         } else {
  1058.                    /* Current class descriptor matches current class.
  1059.              * Some classes may have been inserted.
  1060.              * Record the match and advance the class, continue
  1061.              * with the next descriptor.
  1062.              */
  1063.             classdesc[spClass] = currdesc;
  1064.             classes[spClass] = cl;
  1065.             currclass = cl.getSuperclass();
  1066.         }
  1067.         }
  1068.  
  1069.         /* Allocate a new object.  The object is only constructed
  1070.          * above the highest serializable class and is set to
  1071.          * default values for all more specialized classes.
  1072.          * Remember the next wirehandle goes with the new object
  1073.          */
  1074.         try {
  1075.         currentObject = (currentClass == null) ? 
  1076.             null: allocateNewObject(currentClass, currclass);
  1077.         } catch (NoSuchMethodError e) {
  1078.         throw new InvalidClassException(currclass.getName(),
  1079.                         "NoSuchMethodError");
  1080.         } catch (IllegalAccessException e) {
  1081.         throw new InvalidClassException(currclass.getName(),
  1082.                         "IllegalAccessException");
  1083.         } catch (InstantiationException e) {
  1084.         throw new InvalidClassException(currclass.getName(),
  1085.                         "InstantiationException");
  1086.         }
  1087.         handle = assignWireOffset(currentObject);
  1088.         
  1089.         /* 
  1090.          * For all the pushed descriptors and classes.
  1091.          * If there is a descriptor but no class, skip the
  1092.          * data for that class.
  1093.          * If there is a class but no descriptor, just advance,
  1094.          * The classes fields have already been initialized to default
  1095.          * values.
  1096.          * Otherwise, there is both a descriptor and class,
  1097.          *     if the class has its own writeObject and readObject methods
  1098.          *        set blockData = true; and call the readObject method
  1099.          *    else
  1100.          *        invoke the defaultReadObject method
  1101.          *    if the stream was written by class specific methods
  1102.          *        skip any remaining data a objects until TC_ENDBLOCKDATA
  1103.          * Avoid setting BlockData=true unless necessary becase it flushes
  1104.          * the buffer.
  1105.          */
  1106.         try {
  1107.         for (spClass = spClass; spClass > spBase; spClass--) {
  1108.             /*
  1109.              * Set current descriptor and corresponding class
  1110.              */
  1111.             currentClassDesc = classdesc[spClass];
  1112.             currentClass = classes[spClass];
  1113.  
  1114.             if (classes[spClass] != null) {
  1115.             /* Read the data from the stream described by the
  1116.              * descriptor and store into the matching class.
  1117.              */
  1118.             setBlockData(true);    /* any reads are from datablocks */
  1119.             ObjectStreamClass localDesc = currentClassDesc.localClassDescriptor();
  1120.             if (!invokeObjectReader(currentObject, currentClass)) {
  1121.                 defaultReadObject();
  1122.             }
  1123.             } else {
  1124.             /* No local class for this descriptor,
  1125.              * Skip over the data for this class.
  1126.              * like defaultReadObject with a null currentObject.
  1127.              * The native code will read the values but discard them.
  1128.              */
  1129.             if (currentClassDesc.getFieldSequence() != null) {
  1130.                 boolean prevmode = setBlockData(false);
  1131.                 inputClassFields(null, currentClass,
  1132.                          currentClassDesc.getFieldSequence());
  1133.                 setBlockData(prevmode);
  1134.             }
  1135.             }
  1136.  
  1137.             /*
  1138.              * If the source class (stream) had a write object method
  1139.              * it may have written more data and will have written the
  1140.              * TC_ENDBLOCKDATA.  Skip anything up to that and read it.
  1141.              */
  1142.             if (currentClassDesc.hasWriteObject()) {
  1143.             setBlockData(true);
  1144.             SkipToEndOfBlockData();
  1145.             }
  1146.             setBlockData(false);
  1147.         }
  1148.         } finally {
  1149.         // Make sure we exit at the same stack level as when we started.
  1150.         spClass = spBase;
  1151.         }
  1152.     }
  1153.     return handle;
  1154.     }
  1155.  
  1156.     /*
  1157.      * Skip any unread block data and objects up to the next
  1158.      * TC_ENDBLOCKDATA.  Anybody can do this because readObject
  1159.      * handles the details of reporting if there is data left.
  1160.      * Try reading objects.  If it throws optional data
  1161.      * skip over it and try again. 
  1162.      */
  1163.     private void SkipToEndOfBlockData()
  1164.     throws IOException, ClassNotFoundException
  1165.     {
  1166.     while (peekCode() != TC_ENDBLOCKDATA) {
  1167.         try {
  1168.         /* do not require a local Class equivalent of object being read. */
  1169.         Object ignore = readObject(false);
  1170.         } catch (OptionalDataException data) {
  1171.         if (data.length > 0)
  1172.             skip(data.length);
  1173.         }
  1174.     }
  1175.     readCode();            /* Consume TC_ENDBLOCKDATA */
  1176.     }
  1177.     
  1178.     /*
  1179.      * Reset the stream to be just like it was after the constructor.
  1180.      */
  1181.     private void resetStream() throws IOException {
  1182.     if (wireHandle2Object == null)
  1183.         wireHandle2Object = new Vector(100,100);
  1184.     else
  1185.         wireHandle2Object.setSize(0);   // release all references.
  1186.     nextWireOffset = 0;
  1187.  
  1188.     if (classes == null)
  1189.         classes = new Class[20];
  1190.     else {
  1191.         for (int i = 0; i < classes.length; i++)
  1192.         classes[i] = null;
  1193.     }
  1194.     if (classdesc == null)
  1195.         classdesc = new ObjectStreamClass[20];
  1196.     else {
  1197.         for (int i = 0; i < classdesc.length; i++)
  1198.         classdesc[i] = null;
  1199.     }
  1200.     spClass = 0;
  1201.     setBlockData(true);        // Re-enable buffering
  1202.     if (callbacks != null)
  1203.         callbacks.setSize(0);    // discard any pending callbacks
  1204.     }
  1205.  
  1206.     /* Allocate a handle for an object.
  1207.      * The Vector is indexed by the wireHandleOffset
  1208.      * and contains the object.
  1209.      */
  1210.     private int assignWireOffset(Object obj)
  1211.     throws IOException
  1212.     {
  1213.     wireHandle2Object.addElement(obj);
  1214.     if (++nextWireOffset != wireHandle2Object.size())
  1215.       throw new StreamCorruptedException("Elements not assigned in order");;
  1216.     return nextWireOffset-1;
  1217.     }
  1218.  
  1219.     /*
  1220.      * Peek at the next control code in the stream.
  1221.      * If the code has not been peeked at yet, read it from the stream.
  1222.      */
  1223.     private byte peekCode() throws IOException, StreamCorruptedException{
  1224.     while (currCode == 0) {
  1225.  
  1226.         int newcode = in.read();    // Read byte from the underlying stream
  1227.         if (newcode < 0) 
  1228.         throw new EOFException("Expecting code");
  1229.         
  1230.         currCode = (byte)newcode;
  1231.         if (currCode < TC_BASE || currCode > TC_MAX)
  1232.         throw new StreamCorruptedException("Type code out of range, is " + currCode);
  1233.  
  1234.         /* 
  1235.          * Handle reset as a hidden code and reset the stream.
  1236.          */
  1237.         if (currCode == TC_RESET) {
  1238.         if (recursionDepth != 0 ||
  1239.             currentObject != null ||
  1240.             currentClassDesc != null)
  1241.             throw new StreamCorruptedException("Illegal stream state for reset");
  1242.         
  1243.         /* Reset the stream, and repeat the peek at the next code
  1244.          */
  1245.         resetStream();
  1246.         currCode = 0;
  1247.         }
  1248.     }
  1249.     return currCode;
  1250.     }
  1251.     
  1252.     /*
  1253.      * Return the next control code in the stream.
  1254.      * peekCode gets the next code.  readCode just consumes it.
  1255.      */
  1256.     private byte readCode()
  1257.     throws IOException, StreamCorruptedException
  1258.     {
  1259.     byte tc = peekCode();
  1260.     currCode = 0;
  1261.     return tc;
  1262.     }
  1263.     
  1264.     /*
  1265.      * Put back the specified code to be peeked at next time.
  1266.      */
  1267.     private void pushbackCode(byte code) {
  1268.     currCode = code;
  1269.     }
  1270.     /* -----------------------------------------------------*/
  1271.     /*
  1272.      * Implement the InputStream methods.  The stream has
  1273.      * two modes used internally to ObjectInputStream.  When
  1274.      * in BlockData mode, all reads are only from datablocks
  1275.      * as original written. End of data (-1) is returned
  1276.      * if something other than a datablock is next in the stream.
  1277.      * When not in BlockData mode (false), reads pass directly
  1278.      * through to the underlying stream.
  1279.      * The BlockData mode is used to encapsulate data written
  1280.      * by class specific writeObject methods that is intended
  1281.      * only to be read by corresponding readObject method of the 
  1282.      * same class.  The blocking of data allows it to be skipped
  1283.      * if necessary.
  1284.      *
  1285.      * The setBlockData method is used to switch buffering
  1286.      * on and off.  When switching between on and off 
  1287.      * there must be no data pending to be read. This is 
  1288.      * an internal consistency check that will throw an exception. 
  1289.      *
  1290.      */
  1291.     private InputStream in;
  1292.  
  1293.     /*
  1294.      * Count of bytes available from blockData, if zero, call refill
  1295.      * to look for more.  If -1 always return eof (-1)
  1296.      */
  1297.     private int count;
  1298.         
  1299.     private boolean blockDataMode;
  1300.  
  1301.     private byte[] buffer;    // buffer for reading array data
  1302.  
  1303.     /*
  1304.      * Set the blockdata buffering mode.
  1305.      * If it is being set to false after being true there must
  1306.      * be no pending data. If count > 0 a corrupted exception is thrown.
  1307.      */
  1308.     private boolean setBlockData(boolean mode) throws IOException {
  1309.     if (blockDataMode == mode)
  1310.         return mode;
  1311.     if (blockDataMode && count > 0)
  1312.         throw new StreamCorruptedException("Unread data");
  1313.  
  1314.     /* Set count to allow reading or not */
  1315.     count =  mode ? 0 : -1;
  1316.  
  1317.     blockDataMode = mode;
  1318.     return !mode;
  1319.     }
  1320.     
  1321.     /**
  1322.      * Reads a byte of data. This method will block if no input is 
  1323.      * available.
  1324.      * @return     the byte read, or -1 if the end of the
  1325.      *        stream is reached.
  1326.      * @exception IOException If an I/O error has occurred.
  1327.      * @since     JDK1.1
  1328.      */
  1329.     public int read() throws IOException {
  1330.     int data;
  1331.     if (blockDataMode) {
  1332.         while (count == 0)
  1333.         refill();
  1334.         if (count < 0)
  1335.         return -1;            /* EOF */
  1336.         data = in.read();
  1337.         if (data >= 0)
  1338.         count--;
  1339.     } else {
  1340.         data = in.read();        /* read directly from input stream */
  1341.     }
  1342.     return data;
  1343.     }
  1344.  
  1345.     /*
  1346.      * Expect the next thing in the stream is a datablock, If its a
  1347.      * datablock, extract the count of bytes to allow.  If data is not
  1348.      * available set the count to zero.  On error or EOF, set count to -1.
  1349.      */
  1350.     private void refill() throws IOException {
  1351.     count = -1;        /*  No more data to read, EOF */
  1352.     byte code;
  1353.     try {
  1354.         code = peekCode();
  1355.     } catch (EOFException e) {
  1356.         return;
  1357.     }
  1358.     if (code == TC_BLOCKDATA) {
  1359.         code = readCode();            /* Consume the code */
  1360.         int c = in.read();
  1361.         if (c < 0)
  1362.         throw new StreamCorruptedException("EOF expecting count");
  1363.         
  1364.         count = c & 0xff;
  1365.     } else if (code == TC_BLOCKDATALONG) {
  1366.         code = readCode();
  1367.         int b3 = in.read();
  1368.         int b2 = in.read();
  1369.         int b1 = in.read();
  1370.         int b0 = in.read();
  1371.         if ((b3 | b2 | b1 | b0) < 0)
  1372.         throw new StreamCorruptedException("EOF expecting count");
  1373.         int c = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
  1374.         /*
  1375.          * The 32 bit integer size in the long block data format is
  1376.          * signed (unlike like the normal block data format), and
  1377.          * negative values are invalid.
  1378.          */
  1379.         if (c < 0)
  1380.         throw new StreamCorruptedException("Negative block data size");
  1381.  
  1382.         count = c;
  1383.     }
  1384.     }
  1385.     
  1386.     /**
  1387.      * Reads into an array of bytes.  This method will
  1388.      * block until some input is available.
  1389.      * @param b    the buffer into which the data is read
  1390.      * @param off the start offset of the data
  1391.      * @param len the maximum number of bytes read
  1392.      * @return  the actual number of bytes read, -1 is
  1393.      *         returned when the end of the stream is reached.
  1394.      * @exception IOException If an I/O error has occurred.
  1395.      * @since     JDK1.1
  1396.      */
  1397.     public int read(byte[] data, int offset, int length) throws IOException {
  1398.     int v;
  1399.     int i;
  1400.  
  1401.     if (length < 0)
  1402.         throw new IndexOutOfBoundsException();
  1403.  
  1404.     if (blockDataMode) {
  1405.         while (count == 0)
  1406.         refill();
  1407.         if (count < 0)
  1408.         return -1;
  1409.         int l = Math.min(length, count);
  1410.         i = in.read(data, offset, l);
  1411.         if (i > 0)
  1412.         count -= i;
  1413.         return i;            /* return number of bytes read */
  1414.     } else {
  1415.         /* read directly from input stream */
  1416.         return in.read(data, offset, length);
  1417.     }
  1418.     }
  1419.  
  1420.     /**
  1421.      * Returns the number of bytes that can be read without blocking.
  1422.      * @return the number of available bytes.
  1423.      * @since     JDK1.1
  1424.      */
  1425.     /*
  1426.      * If in blockdataMode returns the number of bytes in the
  1427.      * current block. If that is zero, it will try to read
  1428.      * another blockdata from the stream if any data is available from the
  1429.      * underlying stream..
  1430.      * If not in blockdata mode it returns zero.
  1431.      */
  1432.     public int available() throws IOException {
  1433.     if (blockDataMode) {
  1434.         if (count == 0 && in.available() > 0)
  1435.         refill();
  1436.         if (count >= 0) {
  1437.         return count;
  1438.         } else
  1439.         return 0;    /* EOF is no bytes available */
  1440.     } else {
  1441.         return 0;        /* Not blockdata, no bytes available */
  1442.     }
  1443.     }
  1444.  
  1445.     /**
  1446.      * Closes the input stream. Must be called
  1447.      * to release any resources associated with
  1448.      * the stream.
  1449.      * @exception IOException If an I/O error has occurred.
  1450.      * @since     JDK1.1
  1451.      */
  1452.     public void close() throws IOException {
  1453.     in.close();
  1454.     }
  1455.  
  1456.     /* -----------------------------------------------------*/
  1457.     /*
  1458.      * Provide the methods to implement DataInput.
  1459.      * They delegate to an Instance of DataInputStream that
  1460.      * reads its input from the ObjectInputStream.
  1461.      * This allows this stream to manage the blocked data the data
  1462.      * as necessary.
  1463.      */
  1464.     private DataInputStream dis;
  1465.     
  1466.     /**
  1467.      * Reads in a boolean.
  1468.      * @return the boolean read.
  1469.      * @exception EOFException If end of file is reached.
  1470.      * @exception IOException If other I/O error has occurred.
  1471.      * @since     JDK1.1
  1472.      */
  1473.     public boolean readBoolean() throws IOException {
  1474.     return dis.readBoolean();
  1475.     }
  1476.  
  1477.     /**
  1478.      * Reads an 8 bit byte.
  1479.      * @return the 8 bit byte read.
  1480.      * @exception EOFException If end of file is reached.
  1481.      * @exception IOException If other I/O error has occurred.
  1482.      * @since     JDK1.1
  1483.      */
  1484.     public byte readByte() throws IOException  {
  1485.     return dis.readByte();
  1486.     }
  1487.  
  1488.     /**
  1489.      * Reads an unsigned 8 bit byte.
  1490.      * @return the 8 bit byte read.
  1491.      * @exception EOFException If end of file is reached.
  1492.      * @exception IOException If other I/O error has occurred.
  1493.      * @since     JDK1.1
  1494.      */
  1495.     public int readUnsignedByte()  throws IOException {
  1496.     return dis.readUnsignedByte();
  1497.     }
  1498.  
  1499.     /**
  1500.      * Reads a 16 bit short.
  1501.      * @return the 16 bit short read.
  1502.      * @exception EOFException If end of file is reached.
  1503.      * @exception IOException If other I/O error has occurred.
  1504.      * @since     JDK1.1
  1505.      */
  1506.     public short readShort()  throws IOException {
  1507.     return dis.readShort();
  1508.     }
  1509.  
  1510.     /**
  1511.      * Reads an unsigned 16 bit short.
  1512.      * @return the 16 bit short read.
  1513.      * @exception EOFException If end of file is reached.
  1514.      * @exception IOException If other I/O error has occurred.
  1515.      * @since     JDK1.1
  1516.      */
  1517.     public int readUnsignedShort() throws IOException {
  1518.     return dis.readUnsignedShort();
  1519.     }
  1520.  
  1521.     /**
  1522.      * Reads a 16 bit char.
  1523.      * @return the 16 bit char read. 
  1524.      * @exception EOFException If end of file is reached.
  1525.      * @exception IOException If other I/O error has occurred.
  1526.      * @since     JDK1.1
  1527.      */
  1528.     public char readChar()  throws IOException {
  1529.     return dis.readChar();
  1530.     }
  1531.  
  1532.     /**
  1533.      * Reads a 32 bit int.
  1534.      * @return the 32 bit integer read.
  1535.      * @exception EOFException If end of file is reached.
  1536.      * @exception IOException If other I/O error has occurred.
  1537.      * @since     JDK1.1
  1538.      */
  1539.     public int readInt()  throws IOException {
  1540.     return dis.readInt();
  1541.     }
  1542.  
  1543.     /**
  1544.      * Reads a 64 bit long.
  1545.      * @return the read 64 bit long.
  1546.      * @exception EOFException If end of file is reached.
  1547.      * @exception IOException If other I/O error has occurred.
  1548.      * @since     JDK1.1
  1549.      */
  1550.     public long readLong()  throws IOException {
  1551.     return dis.readLong();
  1552.     }
  1553.  
  1554.     /**
  1555.      * Reads a 32 bit float.
  1556.      * @return the 32 bit float read.
  1557.      * @exception EOFException If end of file is reached.
  1558.      * @exception IOException If other I/O error has occurred.
  1559.      * @since     JDK1.1
  1560.      */
  1561.     public float readFloat() throws IOException {
  1562.     return dis.readFloat();
  1563.     }
  1564.  
  1565.     /**
  1566.      * Reads a 64 bit double.
  1567.      * @return the 64 bit double read.
  1568.      * @exception EOFException If end of file is reached.
  1569.      * @exception IOException If other I/O error has occurred.
  1570.      * @since     JDK1.1
  1571.      */
  1572.     public double readDouble() throws IOException {
  1573.     return dis.readDouble();
  1574.     }
  1575.  
  1576.     /**
  1577.      * Reads bytes, blocking until all bytes are read.
  1578.      * @param b    the buffer into which the data is read
  1579.      * @exception EOFException If end of file is reached.
  1580.      * @exception IOException If other I/O error has occurred.
  1581.      * @since     JDK1.1
  1582.      */
  1583.     public void readFully(byte[] data) throws IOException {
  1584.     dis.readFully(data);
  1585.     }
  1586.  
  1587.     /**
  1588.      * Reads bytes, blocking until all bytes are read.
  1589.      * @param b    the buffer into which the data is read
  1590.      * @param off the start offset of the data
  1591.      * @param len the maximum number of bytes to read
  1592.      * @exception EOFException If end of file is reached.
  1593.      * @exception IOException If other I/O error has occurred.
  1594.      * @since     JDK1.1
  1595.      */
  1596.     public void readFully(byte[] data, int offset, int size) throws IOException {
  1597.     if (size < 0)
  1598.         throw new IndexOutOfBoundsException();
  1599.     
  1600.     dis.readFully(data, offset, size);
  1601.     }
  1602.  
  1603.     /**
  1604.      * Skips bytes, block until all bytes are skipped.
  1605.      * @param n the number of bytes to be skipped
  1606.      * @return    the actual number of bytes skipped.
  1607.      * @exception EOFException If end of file is reached.
  1608.      * @exception IOException If other I/O error has occurred.
  1609.      * @since     JDK1.1
  1610.      */
  1611.     public int skipBytes(int len) throws IOException {
  1612.     return dis.skipBytes(len);
  1613.     }
  1614.  
  1615.     /**
  1616.      * Reads in a line that has been terminated by a \n, \r, 
  1617.      * \r\n or EOF.
  1618.      * @return a String copy of the line.
  1619.      * @since     JDK1.1
  1620.      */
  1621.     public String readLine() throws IOException {
  1622.     return dis.readLine();
  1623.     }
  1624.  
  1625.     /**
  1626.      * Reads a UTF format String.
  1627.      * @return the String.
  1628.      * @since     JDK1.1
  1629.      */
  1630.      public String readUTF() throws IOException {
  1631.     return dis.readUTF();
  1632.     }
  1633.     
  1634.     /* Remember the first exception that stopped this stream. */
  1635.     private IOException abortIOException = null;
  1636.     private ClassNotFoundException abortClassNotFoundException = null;
  1637.  
  1638.     /* Read the fields of the specified class.
  1639.      * The native implementation sorts the field names to put them
  1640.      * in cononical order, ignores transient and static fields
  1641.      * and invokes the appropriate write* method on this class.
  1642.      */
  1643.     private native void inputClassFields(Object o, Class cl, int[] fieldSequence)
  1644.     throws InvalidClassException,
  1645.         StreamCorruptedException, ClassNotFoundException, IOException;
  1646.  
  1647.     /* Allocate a new object for the specified class
  1648.      * Native since newInstance may not be able to find a zero arg constructor.
  1649.      */
  1650.     private static native Object allocateNewObject(Class aclass, Class initclass)
  1651.     throws InstantiationException, IllegalAccessException;
  1652.     
  1653.     /* Allocate a new array for the specified class
  1654.      * Native since the type of the array needs to be set to the class
  1655.      */
  1656.     private static native Object allocateNewArray(Class aclass, int length);
  1657.     
  1658.     /* Test if readObject/Writer methods are present, if so
  1659.      * invoke the reader and return true.
  1660.      */
  1661.     private native boolean invokeObjectReader(Object o, Class aclass)
  1662.     throws InvalidClassException,
  1663.         StreamCorruptedException, ClassNotFoundException, IOException;
  1664.  
  1665.     
  1666.     /* The object is the current object and class is the the current
  1667.      * subclass of the object being read. Nesting information is kept
  1668.      * on the stack.
  1669.      */
  1670.     private Object currentObject;
  1671.     private ObjectStreamClass currentClassDesc;
  1672.     private Class currentClass;
  1673.  
  1674.     /* Arrays used to keep track of classes and ObjectStreamClasses
  1675.      * as they are being merged; used in inputObject.
  1676.      * spClass is the stack pointer for both.
  1677.      */
  1678.     ObjectStreamClass[] classdesc;
  1679.     Class[] classes;
  1680.     int spClass;
  1681.  
  1682.     /* During deserialization the objects in the stream are represented by
  1683.      * handles (ints), they need to be mapped to the objects.
  1684.      * The vector is indexed by the offset between baseWireHandle and the
  1685.      * wire handle in the stream.
  1686.      */
  1687.     private Vector wireHandle2Object;
  1688.     private int nextWireOffset;
  1689.  
  1690.     /* Vector of validation callback objects
  1691.      * The vector is created as needed, and ValidationCallback objects added
  1692.      * for each call to registerObject. The vector is maintained in
  1693.      * order of highest (first) priority to lowest
  1694.      */
  1695.     private Vector callbacks;
  1696.  
  1697.     /* Recursion level, starts at zero and is incremented for each entry
  1698.      * to readObject.  Decremented before exit.
  1699.      */ 
  1700.     private int recursionDepth;
  1701.  
  1702.     /* Last code Peek'ed, if any */
  1703.     private byte currCode;
  1704.  
  1705.     /* 
  1706.      * Flag set to true to allow resolveObject to be called.
  1707.      * Set by enableResolveObject.
  1708.      */
  1709.     boolean enableResolve;
  1710.     
  1711.     /*
  1712.      * RMI over IIOP hook: Flag to indicate if we are
  1713.      * a trusted subclass that has implemented the delegate
  1714.      * interface "sun.io.ObjectInputStreamDelegate".
  1715.      */
  1716.     private boolean isTrustedSubclass = false;
  1717. }
  1718.  
  1719. // Internal class to hold the Callback object and priority
  1720. class ValidationCallback {
  1721.     ValidationCallback(ObjectInputValidation cb, int prio) {
  1722.     callback = cb;
  1723.     priority = prio;
  1724.     }
  1725.  
  1726.     int priority;            // priority of this callback
  1727.     ObjectInputValidation callback; // object to be called back
  1728. }
  1729.